package model.roomManagement.Implementation;



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.util.ArrayList;

import java.util.StringTokenizer;

import controller.textChat.TextChatController;
import controller.textChat.Interface.TextChatControl;




import model.audio.AudioCaptureModel;
import model.audio.AudioMixerModel;
import model.audio.AudioTransmissionModel;
import model.audio.Interface.IPObserver;
import model.infocenter.ClientUserInformations;
import model.roomManagement.Interface.IPObservable;

import model.roomManagement.Interface.IRoomManageModel;
import model.roomManagement.Interface.IServer;
import model.roomManagement.Interface.IUser;
import model.roomManagement.Interface.ViewObservable;
import model.roomManagement.Interface.ViewObserver;




public class RoomManageModel implements IRoomManageModel,Runnable,IPObservable,ViewObservable {

	String ip;
    boolean isOpen=false;
	public boolean isOpen() {
		return isOpen;
	}


	public void setOpen(boolean isOpen) {
		this.isOpen = isOpen;
	}



	int roomId=0;
	IUser user;
	 private IServer server;
	static int socketPort=5566;
	
	
	public int getRoomId() {
		return roomId;
	}



	static RoomManageModel instance=null;

	ArrayList<InetSocketAddress> isaList =new ArrayList();
	
	
public ArrayList<InetSocketAddress> getIsaList() {
		return isaList;
	}


public static IPObservable getInstance(){
	return instance;
}

	 
	public int getUserId(){
		return user.getId();
	}
	public ArrayList<User> getUserList() {
		return userList;
	}
	public ArrayList getUserIdList() {
		return userIdList;
	}


	
	 ArrayList<User> userList=new ArrayList();
	 ArrayList userIdList=new ArrayList();
	 
	 ArrayList roomList=new ArrayList();
	 public ArrayList getRoomList() {
		return roomList;
	}


	ArrayList<IPObserver> observers=new ArrayList();
	ArrayList<ViewObserver> viewObservers=new ArrayList();
	 
	 Socket connectSocket; 

	// *******************Socket连接 START**********************
	 //监听线程类 
	 class Connect extends Thread { 
	  BufferedReader reader; 
	  PrintStream ps; 
	  String cname; 

	  RoomManageModel chatClient; 
	  public  Connect(RoomManageModel client,String name,Socket socket) throws ConnectException { 
	   try { 
	    this.chatClient = client; 
	    connectSocket = socket; 
	     this.cname = name; 
	     reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
	     ps = new PrintStream(socket.getOutputStream()); 
	   } catch (IOException e) { 
		   throw new ConnectException();
	   } 
	   

	   
	  } 
	  
	  
	  //********Heart Test************
	  class HeartInfoSender extends Thread { 
		  
		  public void run(){
			  while(true){

				  ps.println("HeartTest");
				  try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			  }
			  
		  }
	  }
	  
	  //********Heart Test************	  
	  
	  public void run() { 
		  Thread send=new Thread(new HeartInfoSender()); //发送心跳包
		  send.start();
		
	   while (true) { 
	    String line=null ; 
	    try { 
	    line = reader.readLine(); //读取数据流 
	 
	   }catch (Exception ex) {
	   
		   notifyViewObservers(new ConnectException());
		   
	    ex.printStackTrace(); 
	    ////////////////////
	    ps.println("quit");; //断开连接 
	  
	    return; 
	   } 
	   StringTokenizer stinfo = new StringTokenizer(line,":"); //分解字符串 
	   String keyword = stinfo.nextToken(); 

	  if (keyword.equals("updata")){
		 

	   updataInfo(stinfo);
	
	   
	   } 
	  else if(keyword.equals("updataIp")){
		  ip=stinfo.nextToken();
		  ClientUserInformations.getInstance().setIp(ip);

	  }
	     } 
	   
	   }

	 } 

//*******************Socket连接 END**********************
	 

	 
	 Socket socket = null;//连接端口 
	 PrintStream ps = null;//输出流 
	 Connect connect = null; 
	 


	 
	 public void connect() throws ConnectException{
		try{ 
		//	connectAudio();//连接语音
		 
		 
		 socket = new Socket(LoginModel.serverIp,socketPort);//实例化一个套接字 
		

			
	     ps = new PrintStream(socket.getOutputStream());//获取输出流，写入信息 
	     StringBuffer info = new StringBuffer("info:"); 
	     String userinfo = user.getName()+":"+user.getId(); 
	     ps.println(info.append(userinfo));//输出信息 
	     ps.flush(); 
	     connect = new  Connect(this,user.getName(),socket); 
	     connect.start(); 
		}
		catch(Exception e){
			 throw new ConnectException();
		}
	 }
	 
	 public void disconnect() { //断开连接方法 
	  if (socket != null) { 
	   ps.println("quit");//发送信息 
	   ps.flush(); 
	    
	   socket = null; 

	  } 
	 } 

	 
	 
	 
	 
	 
	public RoomManageModel(IUser user, IServer server,Socket socket) throws ConnectException{
		this.server=server;
		this.user=user;
		this.roomList=getRoomByUId(user.getId());
		ClientUserInformations.getInstance().setUserId(user.getId());
		ClientUserInformations.getInstance().setUserName(user.getName());
		instance=this;
	
		try {
			connect();
		} catch (Exception e) {
			 throw new ConnectException();
		}
		
	
		
	
		
		 
	}
	

	public void run() {
			// TODO Auto-generated method stub
			
		} 
	 
	//private void test() {
	//	IRoomManageController RMC=new RoomManageController(this);
    //    String fileName="01.doc";
       
     //   int fileRoom=19;
        //String kind=null;
    //   System.out.println(user.getId()+" "+user.getName()+" "+" "+user.getRoomList());
     // try{
      //    File file = new File(fileName);
     //      server.deletRoom(user.getId(), 7);
      //	server.storedFile(file, fileRoom,user.getId());
      //	server.readFile(fileName,fileRoom);
    
      //    System.out.print( server.deletFile(fileName,fileRoom,user.getId()));
        
      //  getRoomByUId(user.getId());
     //     getUserByRId(2);
          
   //   }catch(Exception e){
   //        e.printStackTrace();
   //        System.out.print("False");
   //   }

		
		///////////////////////////
		//int roomId=RMC.creatRoom("FIRST", "123456");
		//RMC.quit(roomId);
		//RMC.join(1, "123456");
	//	RMC.join(4, "123456");
	//	System.out.println(RMC.enter(4));
	//	RMC.exit();
	//	
	//	System.out.println(RMC.deletRoom(2));
	//}


	@Override
	public int creatRoom(String subject, String password) {
	
		try {////
			
			roomId=server.creatRoom(user.getId(),subject,password);
		} catch (RemoteException e) {
			
			e.printStackTrace();
			 notifyViewObservers(new ConnectException()); //连接错误
		}
		////////////////////////

		
		return roomId;
	}

	@Override
	public boolean deletRoom(int roomId) {
		boolean success=false;
		try {
			success=server.deletRoom(user.getId(), roomId);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return success;
	}

	@Override
	public boolean enter(int roomId) {
		boolean isSuccess=false;
		try {
			isSuccess=server.userEnter(user.getId(), roomId);
	
			
		} catch (Exception e) {
			
			e.printStackTrace();
			notifyViewObservers(new ConnectException());
			return false;
		}
		
		if(isSuccess){
			
			this.roomId=roomId;
			ClientUserInformations.getInstance().setCurRoomId(roomId);
			userList.add((User)user);
			
			ps.println("roomId:"+roomId);
			getUserIdByRId();//得到该房间的userId
		}
		return isSuccess;
	}


	@Override
	public boolean exit() {
		
		try {
			roomId=-1;
			ClientUserInformations.getInstance().setCurRoomId(roomId);
			  if (socket != null) { 
				   ps.println("exitRoom");//发送信息 
				   ps.flush();
			  }
		} catch (Exception e) {
	
			e.printStackTrace();
			return false;
		}
         notifyViewObservers();
		return true;
		
	}


	@Override
	public boolean join(int roomId,String password) {
		boolean success=false;
		try {
			success= server.userJoin(user.getId(), roomId,password);
			
		} catch (RemoteException e) {

			e.printStackTrace();
		}

		return success;
	}

	@Override
	public boolean quit(int roomId) {
		
		boolean success=false;
		try {
			success= server.userQuit(user.getId(), roomId);
		
			
		} catch (RemoteException e) {
	
			e.printStackTrace();
		}
		
	 return success;
	}
  

	@Override
	public void quitTheSystem() {
		disconnect();
		System.exit(0);
		
	}

	public ArrayList getRoomByUId(int userId){
		try {
			
			return server.getRoomByUId(userId);
			
		} catch (RemoteException e) {
			 notifyViewObservers(new ConnectException());
		}
		return null;
	};
	public void getUserIdByRId(){//得到房间用户 ID
		
		try {
			userIdList=server.getUserByRId(roomId);
			
		} catch (RemoteException e) {
			 notifyViewObservers(new ConnectException());
		}
	};
	
	private void getCurrentInfo(StringTokenizer st){//更新房间用户 IP
	
		String info=null;
		StringTokenizer stinfo =st;
		StringTokenizer stinfo2 =null;
	
		userList.clear();
		isaList.clear();
		while(stinfo.hasMoreTokens()){
				info=stinfo.nextToken();
				stinfo2 = new StringTokenizer(info,"/"); //分解字符串 
	            User u=new User();
	            u.setIp(stinfo2.nextToken());
	            u.setPort(Integer.parseInt(stinfo2.nextToken()));

	            
	            u.setId(Integer.parseInt(stinfo2.nextToken()));
	            u.setName(stinfo2.nextToken());
	            
	            	
				    userList.add(u);

				    if(!(u.getIp().startsWith(ip)))
					isaList.add(u.getAudioInetSocketAddress());//把自己的剔除 
				    
		}
	

	
		
	};
	
	
	
	
	private void updataInfo(StringTokenizer stinfo){
		getCurrentInfo(stinfo);
		notifyObservers();
		notifyViewObservers();

		
	};



	public String getUserInfo() {
		String Info=user.getName()+"/"+user.getId();
		return Info;
	}

	@Override
	public String getRoomInfoByRId(int roomId) {
		
		try {
			return server.getRoomInfoByRId(roomId);
		} catch (RemoteException e) {
	
			 notifyViewObservers(new ConnectException());
			return null;
		}
	}




	@Override
	public void addObserver(IPObserver ipObserver) {

		observers.add(ipObserver);

	}




	@Override
	public void notifyObservers() {

		for(int i=0;i<observers.size();i++){
			observers.get(i).updateAddresses(isaList);//ipobserver

		}
		
	}


	@Override
	public void addViewObserver(ViewObserver viewObserver) {
		viewObservers.add(viewObserver);
		
	}


	@Override
	public void notifyViewObservers() {
		for(int i=0;i<viewObservers.size();i++){
			viewObservers.get(i).updata();

		}
		
	}

	private void notifyViewObservers(ConnectException connectException) {
		for(int i=0;i<viewObservers.size();i++){
			viewObservers.get(i).exceptionInfo( connectException);

		}
		
	} 


	@Override
	public boolean changePassWord(String oldPassword, String newPassword) {
		
		try {
			return server.changePassWord(ClientUserInformations.getInstance().getUserId(),oldPassword,newPassword);
		} catch (RemoteException e) {
			 notifyViewObservers(new ConnectException());
			return false;
		}
	}









	
	
}
